package networked;

import com.jme3.app.SimpleApplication;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.network.HostedConnection;
import com.jme3.network.Message;
import com.jme3.network.MessageListener;
import com.jme3.network.Network;
import com.jme3.network.Server;
import com.jme3.system.JmeContext;
import com.simsilica.es.EntityData;
import com.simsilica.es.EntityId;
import com.simsilica.es.sql.SqlEntityData;
import de.tsajar.es.EntityDataAppState;
import de.tsajar.es.arrow.ArrowComponent;
import de.tsajar.es.arrow.ArrowSystem;
import de.tsajar.es.networking.server.EntityDataServerState;
import de.tsajar.es.physics.VelocityComponent;
import de.tsajar.es.position.PositionComponent;
import de.tsajar.es.position.RotationComponent;
import de.tsajar.es.render.RenderComponent;
import de.tsajar.es.render.RenderSystem;
import de.tsajar.es.expiration.ExpirationComponent;
import de.tsajar.es.expiration.ExpirationSystem;
import de.tsajar.es.physics.SolidComponent;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import modelinitializer.CubeInitializer;

/**
 *
 * @author Eike Foede
 */
public class TestArrowServer extends SimpleApplication implements MessageListener<HostedConnection> {

    EntityData ed;
    EntityDataServerState eds;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        TestArrowServer tr = new TestArrowServer();

//        tr.start();
        tr.start(JmeContext.Type.Headless);
    }

    private void addScene() {

        EntityId id = ed.createEntity();
        ed.setComponents(id, new RenderComponent("scene"),
                new PositionComponent(Vector3f.ZERO),
                new RotationComponent(Quaternion.DIRECTION_Z),
                new SolidComponent());
    }

    private void initServer(int port) {

        Helper.initSerializers();
        try {
            Server s = Network.createServer(port);
            s.start();
            s.addMessageListener(this, ShootMessage.class);
            stateManager.attach(new EntityDataServerState(s));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    @Override
    public void simpleInitApp() {
        flyCam.setMoveSpeed(10);
//        try {
//            stateManager.attach(new EntityDataAppState(new SqlEntityData("./db", 100)));
//            
//        } catch (SQLException ex) {
//            Logger.getLogger(TestArrowServer.class.getName()).log(Level.SEVERE, null, ex);
//            System.exit(1);
//        }
        stateManager.attach(new EntityDataAppState());
        ed = stateManager.getState(EntityDataAppState.class).getEd();
        stateManager.attach(new ArrowSystem(rootNode));
        stateManager.attach(new RenderSystem(new CubeInitializer(assetManager)));//Unclean, necessary for collision detection
        stateManager.attach(new ExpirationSystem());
        initServer(1234);
        addScene();
    }

    private void fireArrow(Vector3f location, Vector3f direction) {
        EntityId id = ed.createEntity();
        ed.setComponent(id, new PositionComponent(location));
        ed.setComponent(id, new RotationComponent(Quaternion.DIRECTION_Z));
        ed.setComponent(id, new RenderComponent("arrow"));
        ed.setComponent(id, new ArrowComponent());
        Vector3f randVec = new Vector3f((float) Math.random(), (float) Math.random(), (float) Math.random());
        randVec.subtractLocal(Vector3f.UNIT_XYZ.mult(0.5f));
        randVec.multLocal(3);
        randVec.multLocal(randVec.mult(randVec));
        float error = 0.001f;
        ed.setComponent(id, new VelocityComponent(direction.add(randVec.mult(error)).mult(45)));
        ed.setComponent(id, new ExpirationComponent(30));
    }

    public void messageReceived(HostedConnection source, Message m) {
        if (m instanceof ShootMessage) {
            ShootMessage sm = (ShootMessage) m;
            fireArrow(sm.getPos(), sm.getDir());
        }
    }
}
